/*
 * Copyright (C) 2012 by Hao Hou<ghost89413@gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>*
 */
#include <protocol.h>
#include <stdio.h>
#include <log.h>
#include <event.h>
#include <ic.h>
inline void __protocol_log__(IMForwardEventStruct* data)
{
#define XIM_EVENT_LOG(name) case name : VINE_LOG_DEBUG("XIM Event: "#name"\ticid=%d\tconid=%d",\
		data->icid,data->connect_id);\
		break
	switch(data->major_code)
	{
		XIM_EVENT_LOG(XIM_OPEN);
		XIM_EVENT_LOG(XIM_CLOSE);
		XIM_EVENT_LOG(XIM_CREATE_IC);
		XIM_EVENT_LOG(XIM_DESTROY_IC);
		XIM_EVENT_LOG(XIM_SET_IC_VALUES);
		XIM_EVENT_LOG(XIM_GET_IC_VALUES);
		XIM_EVENT_LOG(XIM_FORWARD_EVENT);
		XIM_EVENT_LOG(XIM_SET_IC_FOCUS);
		XIM_EVENT_LOG(XIM_UNSET_IC_FOCUS);
		XIM_EVENT_LOG(XIM_TRIGGER_NOTIFY);
		XIM_EVENT_LOG(XIM_RESET_IC);
	default: 
		VINE_LOG_DEBUG("XIM Event: major_code=%d\ticid=%d\tconid%d",
				data->major_code,
				data->icid,
				data->connect_id);
	}
#undef XIM_EVEN_LOG  //local macro should not be used outside of the function ...
}
#define XIM_EVENT_PROC(name) int XIMProc##name(IMProtocol*  proto)
XIM_EVENT_PROC(OPEN)
{
	return 1;
}
XIM_EVENT_PROC(CREATE_IC)
{
	IMChangeICStruct* param = (IMChangeICStruct*) proto;
	param->icid = 0;
	return (ModifyIC(param) >= 0);	//when ModifyIC returns -1, it implies an error 
}
XIM_EVENT_PROC(GET_IC_VALUES)
{
	return (QueryIC((IMChangeICStruct*) proto) >= 0);
}
XIM_EVENT_PROC(SET_IC_VALUES)
{
	return (ModifyIC((IMChangeICStruct*) proto) >= 0);
}
XIM_EVENT_PROC(TRIGGER_NOTIFY)
{
	//TODO: Tri
	return 1;
}
XIM_EVENT_PROC(FORWARD_EVENT)
{
	return (EventHandler((IMForwardEventStruct*)proto) >= 0);
}
XIM_EVENT_PROC(DESTROY_IC)
{
	InputContext* ic = FindIC(proto->changeic.icid);
	if(NULL == ic) return 1;
	ICDestory(ic);
	return 1;
}
XIM_EVENT_PROC(SET_IC_FOCUS)
{
	//TODO
	InputContext* ic = FindIC(proto->changefocus.icid);
	RedrawIC(ic);
	if(ic->IMWindowVisable)
	{
		//ISSUE: Redraw Candidates
		//ShowIMWindow();
		UpdateCandidates(ic, ic->Candidates.Candidate, ic->Candidates.Count);
	}
	return 1;
}
XIM_EVENT_PROC(UNSET_IC_FOCUS)
{
	//TODO
	InputContext* ic = FindIC(proto->changefocus.icid);
	if(ic->IMWindowVisable)
	{
		HideIMWindow();
	}
	SetTrayIcon(default_tray_icon);
	SetTrayToolTip("Vine(No Input Window)");
	return 1;
}
#undef XIM_EVENT_PROC
int VineProtocolHandler(XIMS ims,IMProtocol* proto)
{
	__protocol_log__((IMForwardEventStruct *) proto);
#define REGISTER_PROC(name) case XIM_##name: return XIMProc##name(proto)
	switch(proto->major_code)
	{
		REGISTER_PROC(OPEN);
		REGISTER_PROC(CREATE_IC);
		REGISTER_PROC(DESTROY_IC);
		REGISTER_PROC(SET_IC_VALUES);
		REGISTER_PROC(GET_IC_VALUES);
		REGISTER_PROC(SET_IC_FOCUS);
		REGISTER_PROC(UNSET_IC_FOCUS);
		REGISTER_PROC(FORWARD_EVENT);
		REGISTER_PROC(TRIGGER_NOTIFY);
		default: return 1;
	}
#undef REGISTER_PROC
}
